define
(
    ["./Frame",
     "Common/ObjectUtilities",
     "Common/OrderedChangeIdSet"],
    function(Frame, 
                 ObjectUtilities,
                 OrderedChangeIdSet)
    {
        return function(changeId, name, description)
        {            
            var _frames = new OrderedChangeIdSet();
            var _elementId = 0;

            this.changeId = changeId;
            this.name = name;
            this.description = description;
            
            this.createElement = function(frameChangeId, element)
            {
                var frame = _frames.find(frameChangeId);

                if (!frame)
                {
                    // TODO: Return error
                    return;
                }

                var elementId = _elementId++;

                frame.addShape(elementId, element);

                return elementId;
            };

            this.deleteElements = function(frameChangeId, changeIds)
            {
                var frame = _frames.find(frameChangeId);

                if (!frame)
                {
                    return;
                }

                for (var i = 0; i < changeIds.length; i++)
                {
                    frame.deleteShape(changeIds[i]);
                }
            };

            this.modifyElements = function(frameChangeId, elements)
            {
                var frame = _frames.find(frameChangeId);

                if (!frame)
                {
                    return;
                }

                for (var i = 0; i < elements.length; i++)
                {
                    frame.addShape(elements[i].changeId, elements[i]);
                } 
            };

            this.createFrame = function(frameObj, predecessorFrameId)
            {                
                var frame = new Frame(_elementId++);
                frameObj.changeId = frame.changeId;
                _frames.add(predecessorFrameId, frame);

                for (var i = 0; i < frameObj.shapes.length; i++)
                {
                    frame.addShape(_elementId++, frameObj.shapes[i]);
                }

                return frame;
            };

            this.updateFrameChangeId = function(frame, newChangeId)
            {
                _frames.updateChangeId(frame, newChangeId);
            };

            this.deleteFrame = function(frameChangeId)
            {
                _frames.delete(frameChangeId);
            };

            this.reorderFrame = function(frameChangeId, newIndex)
            {
                var frame = _frames.find(frameChangeId);

                if (!frame)
                {
                    return;
                }

                _frames.reorderObject(frameChangeId, newIndex);
            };

            this.toJSON = function()
            {                
                return {changeId: this.changeId, name: name, description: description, frames: _frames};
            };
        };
    }
);